#ifndef DATABASEUTILS_H
#define DATABASEUTILS_H

#include <QtSql/QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QMetaProperty>
#include <QVariant>
#include <QList>
#include <QDebug>
#include <QObject>
#include <stdexcept>

class QSqlQueryUtil {
private:
    QString connectionName;
    QSqlDatabase database;
    QString databaseName;
    QString databaseType;
    bool isOpenTransaction;

private:
    /**
 * 建立数据库连接
 */
    bool createConnection() {
        if (QSqlDatabase::contains(connectionName)) {
            database = QSqlDatabase::database(connectionName);
        } else {
            database = QSqlDatabase::addDatabase(databaseType, connectionName);
            database.setDatabaseName(databaseName);
        }
        return database.isValid();
    }


    /**
     * 打开数据库
     */
    bool openDataBase() {
        if (!database.open()) {
            qDebug() << "Open database error:" << database.lastError().text();
            return false;
        }
        return true;
    }
public:
    /**
     * 构造方法
     * @param connectionName
     * @param databaseName 数据库名称
     * @param databaseType 连接类型
     * @param isOpenTransaction 是否开启事务
     */
    QSqlQueryUtil(const QString &connectionName, const QString &databaseName, const QString &databaseType, bool isOpenTransaction = false)
        :connectionName(connectionName), databaseName(databaseName), databaseType(databaseType), isOpenTransaction(isOpenTransaction) {
        if (!run()) {
            throw std::runtime_error("Failed to initialize database connection");
        }
    }

    QSqlDatabase getDatabase() const {
        return database;
    }


    ~QSqlQueryUtil() {
        close();
    }

    /**
     * 开启事务
     * @param isOpen
     */
    void setTransactionEnabled(bool isOpen) {
        isOpenTransaction = isOpen;
    }

    /**
     * 运行数据库
     */
    bool run() {
        return createConnection() && openDataBase();
    }

    /**
     * 关闭数据库连接
     */
    void close() {
        if (isOpen()) {
            database.close();
        }
    }

    /**
     * 检查数据库是否打开
     */
    bool isOpen() const {
        return database.isOpen();
    }

    /**
     * 执行查询,并通过反射赋值
     * @tparam T 返回的实体类
     * @param sql 查询语句
     * @param params 参数
     * @return 返回的类型
     */
    // template<typename T>
    // QList<T> executeQuery(const QString &sql, const QVariantList &params = QVariantList());
    QList<QHash<QString, QVariant>> executeQuery(const QString &sql, const QVariantList &params = QVariantList());

    /**
     * 更新语句
     * @param sql
     * @param params
     * @return 返回更新的数量
     */
    int executeUpdate(const QString &sql, const QVariantList &params = QVariantList()) {
        if (!isOpen()) {
            qDebug() << "Database is not open!";
            return -1;
        }

        if (isOpenTransaction) {
            database.transaction();
        }

        QSqlQuery query(database);
        query.prepare(sql);

        for (int i = 0; i < params.size(); ++i) {
            query.bindValue(i, params[i]);
        }

        if (!query.exec()) {
            qDebug() << "executeUpdate error:" << query.lastError().text();
            if (isOpenTransaction) {
                database.rollback();
            }
            return -1;
        }

        if (isOpenTransaction) {
            database.commit();
        }

        return query.numRowsAffected();
    }

    /**
     * 批量插入
     * @param sql sql语句
     * @param params 占位符参数,传列表
     * @return 更新数量
     */
    int batchInsert(const QString &sql, const QList<QVariantList> &paramRows) {
        if (!isOpen()) {
            qDebug() << "Database is not open!";
            return -1;
        }
        database.transaction();
        QSqlQuery query(database);
        query.prepare(sql);
        for (auto paramRow : paramRows){
            query.addBindValue(paramRow);
        }

        if (!query.execBatch()) {
            qDebug() << "Batch insert error:" << query.lastError().text();
            database.rollback();
            return -1;
        }
        database.commit();
        return query.numRowsAffected();
    }

private:
    /**
     * 下划线转驼峰
     * @param fieldName
     */
    void underToCamel(QString &fieldName) {
        int index = -1;
        while ((index = fieldName.indexOf('_')) != -1) {
            if (index < fieldName.length() - 1) {
                fieldName.remove(index, 1);
                if (index < fieldName.length()) {
                    fieldName[index] = fieldName[index].toUpper();
                }
            } else {
                // 如果下划线在末尾，直接删除
                fieldName.remove(index, 1);
                break;
            }
        }
    }

    // /**
    //  * 设置对象属性值
    //  */
    // template<typename T>
    // void setPropertyValue(T &obj, const QMetaProperty &property, const QVariant &value) {
    //     // 对于Gadget使用writeOnGadget，对于QObject使用write
    //     if (std::is_base_of<QObject, T>::value) {
    //         property.write(&obj, value);
    //     } else {
    //         property.writeOnGadget(&obj, value);
    //     }
    // }
};

// 特化版本 for QHash<QString, QVariant>
// template<>
inline QList<QHash<QString, QVariant>> QSqlQueryUtil::executeQuery(const QString &sql, const QVariantList &params) {
    QList<QHash<QString, QVariant>> result;

    if (!isOpen()) {
        qDebug() << "Database is not open!";
        return result;
    }

    QSqlQuery query(database);
    query.prepare(sql);

    for (int i = 0; i < params.size(); ++i) {
        query.bindValue(i, params[i]);
    }

    if (!query.exec()) {
        qDebug() << "Query execution failed:" << query.lastError().text();
        return result;
    }

    QSqlRecord record = query.record();
    while (query.next()) {
        QHash<QString, QVariant> row;
        for (int i = 0; i < record.count(); ++i) {
            QString fieldName = record.fieldName(i);
            QVariant fieldValue = query.value(i);
            row[fieldName] = fieldValue;
        }
        result.append(row);
    }

    return result;
}

// // 模板实现
// template<typename T>
// QList<T> QSqlQueryUtil::executeQuery(const QString &sql, const QVariantList &params) {
//     QList<T> result;
//     if (!isOpen()) {
//         qDebug() << "Database is not open!";
//         return result;
//     }
//     QSqlQuery query(database);
//     query.prepare(sql);
//     for (int i = 0; i < params.size(); ++i) {
//         query.bindValue(i, params[i]);
//     }
//     if (!query.exec()) {
//         qDebug() << "Query execution failed:" << query.lastError().text();
//         return result;
//     }
//     QSqlRecord record = query.record();
//     while (query.next()) {
//         T obj;
//         const QMetaObject* metaObject = obj.metaObject();
//         if (!metaObject) {
//             qDebug() << "No metaobject found for type";
//             continue;
//         }
//         for (int i = 0; i < record.count(); ++i) {
//             QString fieldName = record.fieldName(i);
//             QVariant fieldValue = query.value(i);
//             if (fieldValue.isNull()) {
//                 continue;
//             }
//             // 下划线转驼峰
//             underToCamel(fieldName);
//             int propertyIndex = metaObject->indexOfProperty(fieldName.toUtf8().constData());
//
//             if (propertyIndex != -1) {
//                 QMetaProperty property = metaObject->property(propertyIndex);
//                 if (property.isWritable()) {
//                     try {
//                         setPropertyValue(obj, property, fieldValue);
//                     } catch (const std::exception &e) {
//                         qDebug() << "Failed to set property" << fieldName << ":" << e.what();
//                     }
//                 }
//             }
//         }
//         result.append(obj);
//     }
//
//     return result;
// }

#endif // DATABASEUTILS_H
